package com.ruoyi.yljf.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.yljf.domain.*;
import com.ruoyi.yljf.domain.enums.yljfEnums;
import com.ruoyi.yljf.mapper.*;
import com.ruoyi.yljf.service.ICollectRecordService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 收藏记录Service业务层处理
 *
 * @author metaee
 * @date 2025-04-19
 */
@Service
public class CollectRecordServiceImpl extends ServiceImpl<CollectRecordMapper, CollectRecord> implements ICollectRecordService {
    @Resource
    private CollectRecordMapper collectRecordMapper;

    @Resource
    public StringRedisTemplate stringRedisTemplate;

    @Resource
    private JingfangMapper jingfangMapper;
    @Resource
    private MedicalRecordMapper medicalRecordMapper;
    @Resource
    private DrugMapper drugMapper;

    @Resource
    public CourseMapper courseMapper;

    /**
     * 查询收藏记录列表
     *
     * @param collectRecord 收藏记录
     * @return 收藏记录
     */
    @Override
    public List<CollectRecord> selectCollectRecordList(CollectRecord collectRecord) {
        LambdaQueryWrapper<CollectRecord> queryWrapper = Wrappers.lambdaQuery();
        if (StringUtils.isNotNull(collectRecord.getTargetId())) {
            queryWrapper.eq(CollectRecord::getTargetId, collectRecord.getTargetId());
        }
        if (StringUtils.isNotNull(collectRecord.getUserId())) {
            queryWrapper.eq(CollectRecord::getUserId, collectRecord.getUserId());
        }
        if (StringUtils.isNotEmpty(collectRecord.getTargetType())) {
            queryWrapper.eq(CollectRecord::getTargetType, collectRecord.getTargetType());
        }
        if (StringUtils.isNotNull(collectRecord.getCreateTime())) {
            queryWrapper.eq(CollectRecord::getCreateTime, collectRecord.getCreateTime());
        }
        return collectRecordMapper.selectList(queryWrapper);
    }

    public boolean ifCollect(String targetType, Long targetId, Long userId) {
        // 判断当前登录用户是否已经收藏
        String key = CacheConstants.COLLECT_USERIDS_KEY + targetType + ":" + targetId;
        boolean is = Boolean.TRUE.equals(stringRedisTemplate.opsForSet().isMember(key, userId.toString()));
        if (!is) {
            List<CollectRecord> collectRecords = collectRecordMapper.selectList(new LambdaQueryWrapper<>(CollectRecord.class)
                    .eq(CollectRecord::getTargetType, targetType)
                    .eq(CollectRecord::getTargetId, targetId)
                    .eq(CollectRecord::getUserId, userId)
            );
            is = !(collectRecords == null || collectRecords.isEmpty());
        }
        return is;
    }

    @Transactional
    public String collect(String targetType, Long targetId, Long userId) {
        CollectRecord collectRecord = new CollectRecord();
        collectRecord.setTargetId(targetId);
        collectRecord.setUserId(userId);
        collectRecord.setTargetType(targetType);
        // 1.判断当前登录用户是否已经收藏
        // 1.1 查缓存
        String key = CacheConstants.COLLECT_USERIDS_KEY + ":" + targetType + ":" + targetId;
        boolean is = Boolean.TRUE.equals(stringRedisTemplate.opsForSet().isMember(key, userId.toString()));
        if (!is) {
            //1.2 查数据库
            List<CollectRecord> collectRecords = selectCollectRecordList(collectRecord);
            //1.3 数据库不存在，新增收藏记录
            if (collectRecords == null || collectRecords.isEmpty()) {
                collectRecord.setCreateTime(DateTime.now());
                collectRecordMapper.insert(collectRecord);
                stringRedisTemplate.opsForSet().add(key, String.valueOf(userId));
                is = true;
            } else {
                //1.3 数据库存在，取消收藏
                collectRecordMapper.deleteById(collectRecords.get(0));
                is = false;
            }
        } else {
            //缓存中存在，取消收藏
            List<CollectRecord> collectRecords = selectCollectRecordList(collectRecord);
            collectRecordMapper.deleteById(collectRecords.get(0));
            stringRedisTemplate.opsForSet().remove(key, String.valueOf(userId));
            is = false;
        }
        return is ? "收藏成功" : "取消收藏";
    }

    public List<Course> getCollectCourseList(Long userId) {
        return new CourseRecordTemplate(yljfEnums.COLLECT_TYPE_COURSE.getCode()).getRecord();
    }


    @Override
    public List<Jingfang> selectJingfangRecordListByType(Long userId) {
        return new JingfangRecordTemplate(yljfEnums.COLLECT_TYPE_JINGFANG.getCode()).getRecord();
    }

    @Override
    public List<MedicalRecord> selectMedicalRecordListByType(Long userId) {
        return new MedicalRecordTemplate(yljfEnums.COLLECT_TYPE_MEDICAL.getCode()).getRecord();
    }

    @Override
    public List<Drug> selectDrugRecordListByType(Long userId) {
        return new DrugRecordTemplate(yljfEnums.COLLECT_TYPE_DRUG.getCode()).getRecord();
    }


    public abstract class CollectRecordTemplate<T>{
        String type;
        List<T> getRecord(){
            String key = CacheConstants.COLLECT_TARGETIDS_KEY + type + ":" + SecurityUtils.getUserId();
            Set<String> ids = stringRedisTemplate.opsForSet().members(key);
            List<Long> id;
            if (ids == null || ids.isEmpty()) {
                id = getIds();
            } else {
                id = new ArrayList<>(ids.stream().map(Long::parseLong).collect(Collectors.toSet()));
            }
            if (id == null || id.isEmpty()) return new ArrayList<>();
            PageUtils.startPage();
            return getRecord(id);
        }

        abstract List<Long> getIds();

        abstract List<T> getRecord(List<Long> id);
    }

    public class CourseRecordTemplate extends CollectRecordTemplate<Course>{

        public CourseRecordTemplate(String type){
            this.type = type;
        }

        @Override
        List<Long> getIds() {
            return collectRecordMapper.selectIds(SecurityUtils.getUserId(), type);
        }

        @Override
        List<Course> getRecord(List<Long> id) {
            return courseMapper.selectBatchIds(id);
        }
    }

    public class DrugRecordTemplate extends CollectRecordTemplate<Drug>{

        public DrugRecordTemplate(String type){
            this.type = type;
        }

        @Override
        List<Long> getIds() {
            return collectRecordMapper.selectIds(SecurityUtils.getUserId(), type);
        }

        @Override
        List<Drug> getRecord(List<Long> id) {
            return drugMapper.selectBatchIds(id);
        }
    }

    public class JingfangRecordTemplate extends CollectRecordTemplate<Jingfang>{

        public JingfangRecordTemplate(String type){
            this.type = type;
        }

        @Override
        List<Long> getIds() {
            return collectRecordMapper.selectIds(SecurityUtils.getUserId(), type);
        }

        @Override
        List<Jingfang> getRecord(List<Long> id) {
            return jingfangMapper.selectBatchIds(id);
        }
    }

    public class MedicalRecordTemplate extends CollectRecordTemplate<MedicalRecord>{

        public MedicalRecordTemplate(String type){
            this.type = type;
        }

        @Override
        List<Long> getIds() {
            return collectRecordMapper.selectIds(SecurityUtils.getUserId(), type);
        }

        @Override
        List<MedicalRecord> getRecord(List<Long> id) {
            return medicalRecordMapper.selectBatchIds(id);
        }
    }
}
